#ifdef _WIN32
#include <windows.h>
#include <stdio.h>


// 全局变量 
HINSTANCE g_hInstance;
HWND g_hOverlayWnd = NULL;
HHOOK g_hMouseHook = NULL;

// 添加限流相关变量
static DWORD g_lastScrollTime = 0;
const DWORD SCROLL_INTERVAL = 100; // 限制滚动间隔为100毫秒

// 跟踪点击状态
static BOOL g_isMouseDown = FALSE;

// 简单的限流函数
BOOL IsScrollAllowed() {
    DWORD currentTime = GetTickCount();
    if (currentTime - g_lastScrollTime > SCROLL_INTERVAL) {
        g_lastScrollTime = currentTime;
        return TRUE;
    }
    return FALSE;
}

/**
* @brief 鼠标底层钩子回调函数，在鼠标事件触发效果前调用，用于拦截和处理鼠标点击及滚轮事件。
*
* 该函数通过设置鼠标钩子来捕获全局鼠标事件。它会检查鼠标点击或滚轮操作是否发生在指定的窗口区域内，
* 如果在目标窗口内，则根据事件类型决定是否拦截或放行该事件。
*
* @param nCode 钩子代码，如果小于0则直接传递给下一个钩子；否则表示可以处理。
* @param wParam 消息标识符，如 WM_LBUTTONDOWN、WM_MOUSEWHEEL 等。
* @param lParam 指向 MSLLHOOKSTRUCT 结构的指针，包含鼠标事件的详细信息。
* @return 返回 1 表示拦截该事件；否则调用 CallNextHookEx 继续传递事件。
*/
LRESULT CALLBACK LowLevelMouseProc(int nCode, WPARAM wParam, LPARAM lParam) {
    if (nCode >= 0) {
        // 拦截右键按下和中键按下
        if (wParam == WM_RBUTTONDOWN ||
            wParam == WM_MBUTTONDOWN) {
            MSLLHOOKSTRUCT* pMouseStruct = (MSLLHOOKSTRUCT*)lParam;
            POINT pt = pMouseStruct->pt;
            // 检查点击是否在窗口区域内
            RECT rcWindow;
            // 检索指定窗口的边界矩形的尺寸。 hWnd: 要检索的窗口句柄。 lpRect: 指向一个 RECT 结构，该结构接收窗口的边界矩形。
            GetWindowRect(g_hOverlayWnd, &rcWindow);
            // PtInRect 函数确定指定的点是否位于指定的矩形内。
            if (PtInRect(&rcWindow, pt)) {
                // 在窗口区域内则拦截点击
                return 1;
            }
        }

        // 只处理点击事件（左键按下）
        if (wParam == WM_LBUTTONDOWN) {
            printf("Mouse click detected\n");
            MSLLHOOKSTRUCT* pMouseStruct = (MSLLHOOKSTRUCT*)lParam;
            POINT pt = pMouseStruct->pt;

            // 检查点击是否在窗口区域内
            RECT rcWindow;
            // 检索指定窗口的边界矩形的尺寸。 hWnd: 要检索的窗口句柄。 lpRect: 指向一个 RECT 结构，该结构接收窗口的边界矩形。
            GetWindowRect(g_hOverlayWnd, &rcWindow);
            // PtInRect 函数确定指定的点是否位于指定的矩形内。
            if (PtInRect(&rcWindow, pt)) {
                // 记录按下状态
                g_isMouseDown = TRUE;
                // 在窗口区域内则拦截点击
                return 1;
            }
        }
        // 鼠标左按键释放事件
        if (wParam == WM_LBUTTONUP) {
            MSLLHOOKSTRUCT* pMouseStruct = (MSLLHOOKSTRUCT*)lParam;
            POINT pt = pMouseStruct->pt;

            // 检查点击是否在窗口区域内
            RECT rcWindow;
            // 检索指定窗口的边界矩形的尺寸。 hWnd: 要检索的窗口句柄。 lpRect: 指向一个 RECT 结构，该结构接收窗口的边界矩形。
            GetWindowRect(g_hOverlayWnd, &rcWindow);
            // PtInRect 函数确定指定的点是否位于指定的矩形内。
            if (PtInRect(&rcWindow, pt) &&  g_isMouseDown) {
                g_isMouseDown = FALSE;
                printf("click the area\n");
                // 发送点击事件给java
                return 1;
            } else {
                g_isMouseDown = FALSE;
            }
        }
        // 拦截滚轮事件 WM_MOUSEWHEEL: 鼠标垂直滚轮滚动消息  WM_MOUSEHWHEEL: 鼠标水平滚轮滚动消息
        if (wParam == WM_MOUSEWHEEL || wParam == WM_MOUSEHWHEEL) {
            MSLLHOOKSTRUCT* pMouseStruct = (MSLLHOOKSTRUCT*)lParam;
            POINT pt = pMouseStruct->pt;

            // 检查滚动事件是否在透明窗口范围内
            RECT rcWindow;
            GetWindowRect(g_hOverlayWnd, &rcWindow);
            if (PtInRect(&rcWindow, pt)) {
                // 使用限流函数控制滚动事件频率
                if (IsScrollAllowed()) {
                    printf("Mouse wheel event detected\n");
                    // 这里可以添加实际的滚动处理逻辑
                } else {
                    printf("Scroll event blocked by rate limiter\n");
                    return 1;
                }
            } else {
                // 不在透明窗口范围内，不限流，直接处理
                printf("Mouse wheel event detected outside overlay\n");
                // 这里可以添加实际的滚动处理逻辑
            }

        }
    }
    // 放行此鼠标事件
    return CallNextHookEx(g_hMouseHook, nCode, wParam, lParam);
}

// 覆盖窗口过程 
LRESULT CALLBACK OverlayWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
    switch (message) {
        case WM_CREATE:
            SetLayeredWindowAttributes(hWnd, 0, 180, LWA_ALPHA);
            break;

        case WM_DESTROY:
            if (g_hMouseHook) UnhookWindowsHookEx(g_hMouseHook);
            PostQuitMessage(0);
            break;

        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

/**
 * 注册应用程序所需的窗口类
 *
 * 该函数注册两个窗口类：一个用于覆盖窗口，另一个用于目标窗口。
 * 覆盖窗口具有特定的背景色和窗口过程函数，目标窗口使用默认设置。
 *
 * @return BOOL - 成功注册所有窗口类时返回TRUE，否则返回FALSE
 */
BOOL RegisterWindowClasses() {
    WNDCLASSEX wcOverlay = {0};
    wcOverlay.cbSize  = sizeof(WNDCLASSEX);
    wcOverlay.style  = CS_HREDRAW | CS_VREDRAW;
    wcOverlay.lpfnWndProc  = OverlayWndProc;
    wcOverlay.hInstance = g_hInstance;
    wcOverlay.hCursor = LoadCursor(NULL, IDC_ARROW);
    wcOverlay.hbrBackground  = CreateSolidBrush(RGB(100, 150, 200));
    wcOverlay.lpszClassName  = "OverlayWindowClass";

    if (!RegisterClassEx(&wcOverlay)) {
        return FALSE;
    }
    return TRUE;
}

// 创建覆盖窗口 
BOOL CreateOverlayWindow() {
// 修改窗口创建参数（调整为400x300大小），关键在于 WS_EX_TRANSPARENT 会放行所有事件
    g_hOverlayWnd = CreateWindowEx(
            WS_EX_LAYERED | WS_EX_TOPMOST | WS_EX_TRANSPARENT | WS_EX_TOOLWINDOW,
            "OverlayWindowClass",
            "Click Overlay",
            WS_POPUP | WS_VISIBLE,
            (GetSystemMetrics(SM_CXSCREEN)-400)/2,  // 居中显示
            (GetSystemMetrics(SM_CYSCREEN)-300)/2,
            400, 300,  // 新尺寸
            NULL, NULL, g_hInstance, NULL);

    if (!g_hOverlayWnd) return FALSE;
    // 设置窗口属性，使窗口具有透明效果
    SetLayeredWindowAttributes(g_hOverlayWnd, 0, 180, LWA_ALPHA);
    // 装载鼠标钩子
    g_hMouseHook = SetWindowsHookEx(WH_MOUSE_LL, LowLevelMouseProc, g_hInstance, 0);

    return g_hMouseHook != NULL;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
    g_hInstance = GetModuleHandle(NULL);;

    if (!RegisterWindowClasses()) {
        MessageBox(NULL, "Failed to register window classes", "Error", MB_OK | MB_ICONERROR);
        return 1;
    }

    if (!CreateOverlayWindow()) {
        MessageBox(NULL, "Failed to create overlay window", "Error", MB_OK | MB_ICONERROR);
        return 1;
    }

    MSG msg;
//     从应用程序的消息队列中获取消息，当没有消息时返回0，使循环结束
    while (GetMessage(&msg, NULL, 0, 0)) {
        // 将虚拟键消息转换为字符消息
        TranslateMessage(&msg);
        // 将消息分发给相应的窗口过程函数处理
        DispatchMessage(&msg);
    }

    return (int)msg.wParam;
}
#endif